//
//  String+Extension.swift
//  Lease_IOS
//
//  Created by Mr.wang on 2018/12/20.
//  Copyright © 2018 Mr.wang. All rights reserved.
//
import UIKit

extension String {
    
    var localized: String {
        var languagePath = "en.lproj"
        
        if let userSelectLanguage = AppCache.shared.object(for: APPUserDefault.self).userSelectLanguage {
            switch userSelectLanguage {
            case .chinese:
                languagePath = "zh-Hans.lproj"
            case .english:
                languagePath = "en.lproj"
            case .de:
                languagePath = "de.lproj"
            case .vi:
                languagePath = "vi.lproj"
            }
        }
        
        if let path = Bundle.main.path(forResource: languagePath, ofType: nil),
            let bundle = Bundle.init(path: path) {
            return bundle.localizedString(forKey: self, value: nil, table: "Localizable")
        }
        
        return Bundle.main.localizedString(forKey: self, value: nil, table: nil)
    }
    
    var doubleValue: Double {
        if let value = Double(self) {
            return value
        }
        return 0
    }
    
    var intValue: Int {
        if let value = Int(self) {
            return value
        }
        return 0
    }
    
    var hasChinese: Bool {
        for character in self {
            if ("\u{4E00}" <= character && character <= "\u{9FA5}") {
                return true
            }
        }
        return false
    }
    
    var isEmail: Bool {
        let predicateStr = "^([A-Za-z0-9_.-]+)@([A-Za-z0-9.-]+).([a-z.]{2,6})$"
        let predicate = NSPredicate.init(format: "SELF MATCHES %@", predicateStr)
        return predicate.evaluate(with: self)
    }
    
    func md5() -> String {
        let context = UnsafeMutablePointer<CC_MD5_CTX>.allocate(capacity: 1)
        var digest = Array<UInt8>.init(repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
        CC_MD5_Init(context)
        
        CC_MD5_Update(context, self, CC_LONG(self.lengthOfBytes(using: String.Encoding.utf8)))
        CC_MD5_Final(&digest, context)
        context.deallocate()
        return digest.map { String(format: "%02x", $0) }.joined()
    }
    
    static func random(_ length: Int? = nil) -> String {
        let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var ranStr = ""
        let stringLength: Int
        if let length = length {
            stringLength = length
        } else {
            stringLength = 10 + Int(arc4random_uniform(10))
        }
        for _ in 0..<stringLength {
            let index = Int(arc4random_uniform(UInt32(characters.count)))
            ranStr.append(characters[index...index])
        }
        return ranStr
    }
    
    mutating func setUrlParameter(key: String, value: String) {
        if (self == "") {
            return
        }
        
        if !self.contains("?") {
            self = self + "?"
        }
        
        let urlArray = self.components(separatedBy: "?")
        let url = urlArray[0]
        let newParameters = NSMutableArray(capacity: 1)
        
        if urlArray.count > 1 && urlArray[1] != "" {
            let paramstr = urlArray[1]
            let parameters = paramstr.components(separatedBy: "&")
            
            for parameter in parameters where !parameter.contains(key) {
                newParameters.add(parameter)
            }
        }
        if value.count > 0 {
            newParameters.add(key + "=" + value)
        }
        self = (url + "?" + newParameters.componentsJoined(by: "&"))
    }
    
    func toNSRange(_ range: Range<String.Index>) -> NSRange {
        guard let from = range.lowerBound.samePosition(in: utf16),
            let to = range.upperBound.samePosition(in: utf16) else {
                return NSMakeRange(0, 0)
        }
        return NSMakeRange(utf16.distance(from: utf16.startIndex, to: from), utf16.distance(from: from, to: to))
    }
    
    func rangeOf(string: String, at index: Int) -> NSRange? {
        var contentString = self
        
        for i in 0...index {
            guard let range = contentString.range(of: string) else { return nil }
            if i == index {
                return self.toNSRange(range)
            }
            contentString = contentString.replacingCharacters(in: range, with: "")
        }
        return nil
    }
    
    public func checkAvailable(_ message: String,
                               closure: @escaping (String) -> (Bool) = { $0.count > 0 }) -> Bool {
        if !closure(self) {
            APPHud.shared.showError(status: message)
        }
        return closure(self)
    }
    
    func substring(to index: Int) -> String {
        guard let end_Index = validEndIndex(original: index) else {
            return self
        }
        return String(self[startIndex..<end_Index])
    }
    
    func substring(from index: Int) -> String {
        guard let start_index = validStartIndex(original: index) else {
            return self
        }
        return String(self[start_index..<endIndex])
    }
    
    subscript (range: CountableRange<Int>) -> String {
        guard
            let startIndex = validStartIndex(original: range.lowerBound),
            let endIndex = validEndIndex(original: range.upperBound),
            startIndex <= endIndex else { return "" }
        
        return String(self[startIndex..<endIndex])
    }
    
    subscript (range: CountableClosedRange<Int>) -> String {
        guard
            let start_Index = validStartIndex(original: range.lowerBound),
            let end_Index   = validEndIndex(original: range.upperBound),
            startIndex <= endIndex else { return "" }
        
        if (endIndex.encodedOffset <= end_Index.encodedOffset) {
            return String(self[start_Index..<endIndex])
        }
        return String(self[start_Index...end_Index])
    }
    
    private func validIndex(original: Int) -> String.Index {
        switch original {
        case ...startIndex.encodedOffset : return startIndex
        case endIndex.encodedOffset...   : return endIndex
        default                          : return index(startIndex, offsetBy: original)
        }
    }
    
    private func validStartIndex(original: Int) -> String.Index? {
        guard original <= endIndex.encodedOffset else { return nil }
        return validIndex(original:original)
    }
    
    private func validEndIndex(original: Int) -> String.Index? {
        guard original >= startIndex.encodedOffset else { return nil }
        return validIndex(original:original)
    }
    
    subscript(i: Int) -> Character {
        get {
            let index = self.index(self.startIndex, offsetBy: i)
            return self[index]
        }
    }
    
}

